package com.salton123.soulove.sailfish.video.task

import android.os.Build
import android.text.TextUtils
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.documentfile.provider.DocumentFile
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.ThreadUtils
import com.salton123.app.BaseApplication
import com.salton123.log.XLog
import com.salton123.soulove.app.BuildConfig
import com.salton123.soulove.sailfish.db.SailfishDatabase
import com.salton123.soulove.sailfish.db.VideoItem
import com.salton123.soulove.sailfish.video.SailfishManager
import com.salton123.soulove.utils.Utils
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.util.Arrays
import java.util.Stack

/**
 * Time:10/20/21 10:47 PM
 * Author:
 * Description:
 */
@RequiresApi(Build.VERSION_CODES.R)
class DocumentFileScanTask : IBackgroundTask {
    private val TAG = "DocumentFileScanTask"
    private val rootFile = DocumentFile.fromTreeUri(BaseApplication.sInstance, SailfishManager.androidDataUri)

    override fun launch() {
        SailfishManager.coroutineScope.launch {
            rootFile?.listFiles()?.forEach { item ->
                if (item.isFile) {
                    assembleVideoInfo(item)
                } else if (item.isDirectory) {
                    ThreadUtils.executeByCached(object : SimpleTaskCallback() {
                        override fun doInBackground() {
                            walkTopDown(item) {
                                assembleVideoInfo(it)
                            }
                        }
                    })
                }
            }
        }
    }

    /**
     * 从documentFile中装配视频文件信息
     */
    fun assembleVideoInfo(documentFile: DocumentFile) {
        try {
            val filePath = documentFile.uri.toString()
            Log.d(TAG, "filePath:$filePath")
            if (Utils.filterVideoByMimetype(documentFile)) {
                SailfishManager.videoList?.find { it.filePath == filePath }?.let {
                    Log.i(TAG, "find the same item")
                    if (!FileUtils.isFileExists(filePath)) {
                        SailfishManager.coroutineScope.async {
                            SailfishManager.deleteVideo(it)
                        }
                    }
                } ?: kotlin.run {
                    val videoItem = Utils.retrieveDocumentFile(documentFile)
                    Utils.saveToDb(videoItem)
                }
            } else {
                if (BuildConfig.APP_DEVELOP) {
                    XLog.d(TAG, "assembleVideoInfo:${filePath}")
                }
            }
        } catch (ex: Throwable) {
            ex.printStackTrace()
        }
    }

    /**
     * 遍历文件，取得视频文件
     */
    fun walkTopDown(f: DocumentFile, proc: (DocumentFile) -> Unit) {
        if (f.isDirectory) {
            Arrays.stream(f.listFiles())
                .forEach { child -> walkTopDown(child, proc) }
        } else {
            proc.invoke(f)
        }
    }

    fun stactWalk(documentFile: DocumentFile, callback: (DocumentFile) -> Unit) {
        val stack = Stack<DocumentFile>()
        stack.push(documentFile)
        while (stack.isNotEmpty()) {
            val item = stack.pop()
            if (item.isFile) {
                callback.invoke(item)
            } else {
                item.listFiles().forEach {
                    if (it.isFile) {
                        callback.invoke(it)
                    } else {
                        stack.push(it)
                    }
                }
            }
        }
    }
}